<?php

	/**
	 * @see Bike_Form_Renderer
	 */
	require_once 'Bike/Form/Renderer.php';
	
	/**
	 * @see Zend_Loader
	 */
	require_once 'Zend/Loader.php';
	
	class Bike_Form_Renderer_ExtJs extends Bike_Form_Renderer
	{        const TYPE = 'ExtJs';

		static protected $_handlers;
		static protected $_handlersCallbacks;

        static public function getHandlers()
		{
			return array_merge(array(
				'Zend_Form' => 'Bike_Form_Renderer_ExtJs_Form',
				'Bike_Form' => 'Bike_Form_Renderer_ExtJs_Form',
				'Zend_Form_Element' 			=> 'Bike_Form_Renderer_ExtJs_Field_Text',
				'Zend_Form_Element_Button' 		=> 'Bike_Form_Renderer_ExtJs_Button_Button',
				'Zend_Form_Element_Submit' 		=> 'Bike_Form_Renderer_ExtJs_Button_Submit',
			), (array) self::$_handlers);
		}
		
		static public function getHandlersCallbacks()
		{
			return array_merge(array(
				'elements' 		=> array(__CLASS__, 'getHandlerForElement'),
				'validators' 	=> array(__CLASS__, 'getHandlerForValidator'),		
			), (array) self::$_handlersCallbacks);
		}
		
		static public function getHandlerForElement($source)
		{
			if(preg_match('/^(Zend|Bike)_Form_Element_([_\w\d]+)$/', $source, $matches))
			{
				$className = 'Bike_Form_Renderer_ExtJs_Field_'.$matches[2];
				try
				{
					@Zend_Loader::loadClass($className);
					return $className;
				}
				catch(Zend_Exception $e)
				{
				}
			}
			require_once 'Bike/Form/Renderer/Exception.php';
			throw new Bike_Form_Renderer_Exception('There is no handler for element '.$source);
		}
		
		static public function getHandlerForValidator($source)
		{
			if(preg_match('/^(Zend|Bike)_Validate_([_\w\d]+)$/', $source, $matches))
			{
				$className = 'Bike_Form_Renderer_ExtJs_Field_Validate_'.$matches[2];
				try
				{
					@Zend_Loader::loadClass($className);
					return $className;
				}
				catch(Zend_Exception $e)
				{
				}
			}
			require_once 'Bike/Form/Renderer/Exception.php';
			throw new Bike_Form_Renderer_Exception('There is no handler for validator '.$source);
		}

		static public function getHandler($source)
		{
			$handlers = self::getHandlers();
			if(isset($handlers[$source]))
			{
				return $handlers[$source];
			}
			else
			{
				foreach(self::getHandlersCallbacks() as $callback)
				{
					try
					{
						return call_user_func($callback, $source);
					}
					catch(Bike_Form_Renderer_Exception $e)
					{
					}
				}
			}
			require_once 'Bike/Form/Renderer/Exception.php';
			throw new Bike_Form_Renderer_Exception('There is no handler for '.$source);
		}

		static public function addHandler($source, $handler, $rewrite=True)
		{
			if(!is_array(self::$_handlers))
			{
				self::$_handlers = array();
			}
			if(isset(self::$_handlers[$source]) && !$rewrite)
			{
				require_once 'Bike/Form/Renderer/Exception.php';
				throw new Bike_Form_Renderer_Exception('Handler for source '.$source.' already exists');
			}
			self::$_handlers[$source] = $handler;
		}
		
		static public function addHandlerCallback($label, $callback, $rewrite=True)
		{
			if(!is_array(self::$_handlersCallbacks))
			{
				self::$_handlersCallbacks = array();
			}
			if(isset(self::$_handlersCallbacks[$label]) && !$rewrite)
			{
				require_once 'Bike/Form/Renderer/Exception.php';
				throw new Bike_Form_Renderer_Exception('Handler callback for label '.$label.' already exists');
			}
			self::$_handlersCallbacks[$label] = $callback;
		}		

		static public function removeHandler($Source)
		{
			unset(self::$_handler[$Source]);
		}
		
		static public function removeHandlerCallback($label)
		{
			unset(self::$_handlerCallback[$label]);
		}

		static public function removeHandlers()
		{
			self::$_handlers = Null;
		}
		
		static public function removeHandlersCallbacks()
		{
			self::$_handlersCallbacks = Null;
		}

        public function render(Zend_View_Interface $View = null)
        {        	$object = ($this->getElement() instanceof Bike_Form_Element) ? $this->getElement()->getElement() : $this->getElement();
        	try
        	{
        		$className = $this->getHandler(get_class($object));
        	}
        	catch(Bike_Form_Renderer_Exception $e)
        	{        		if($object instanceof Zend_Form_Element)
        		{        			$className = $this->getHandler('Zend_Form_Element');
        		}
        		else
        		{        			throw $e;
        		}
        	}

			try
			{
				@Zend_Loader::loadClass($className);
			}
			catch(Zend_Exception $e)
			{
				require_once 'Bike/Form/Renderer/Exception.php';
				throw new Bike_Form_Renderer_Exception('Class "'.$className.'" is undefined');
			}
        	$Handler = new $className();
        	if(!$Handler instanceof Bike_Form_Renderer_ExtJs_Abstract)
        	{
        		require_once 'Bike/Form/Renderer/Exception.php';
        		throw new Bike_Form_Renderer_Exception('Class "'.$className.'" is not instance of Bike_Form_Renderer_ExtJs_Abstract');
        	}
        	$Handler->setElement($this->getElement())
        			->setExtJs()
        			->afterSetExtJs();
        	return $Handler->getExtJs();
        }
	}
